home *** CD-ROM | disk | FTP | other *** search
Wrap
WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) NNNNAAAAMMMMEEEE wait, waitpid, wait3 - wait for child processes to stop or terminate CCCC SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS _####_iiii_nnnn_cccc_llll_uuuu_dddd_eeee _<<<<_ssss_yyyy_ssss_////_tttt_yyyy_pppp_eeee_ssss_...._hhhh_>>>> _####_iiii_nnnn_cccc_llll_uuuu_dddd_eeee _<<<<_ssss_yyyy_ssss_////_wwww_aaaa_iiii_tttt_...._hhhh_>>>> _pppp_iiii_dddd______tttt _wwww_aaaa_iiii_tttt _((((_iiii_nnnn_tttt _****_ssss_tttt_aaaa_tttt_pppp_tttt_rrrr_))))_;;;; _pppp_iiii_dddd______tttt _wwww_aaaa_iiii_tttt_pppp_iiii_dddd _((((_pppp_iiii_dddd______tttt _pppp_iiii_dddd_,,,, _iiii_nnnn_tttt _****_ssss_tttt_aaaa_tttt_pppp_tttt_rrrr_,,,, _iiii_nnnn_tttt _oooo_pppp_tttt_iiii_oooo_nnnn_ssss_))))_;;;; _####_iiii_nnnn_cccc_llll_uuuu_dddd_eeee _<<<<_ssss_yyyy_ssss_////_tttt_yyyy_pppp_eeee_ssss_...._hhhh_>>>> _####_iiii_nnnn_cccc_llll_uuuu_dddd_eeee _<<<<_ssss_yyyy_ssss_////_wwww_aaaa_iiii_tttt_...._hhhh_>>>> _####_iiii_nnnn_cccc_llll_uuuu_dddd_eeee _<<<<_ssss_yyyy_ssss_////_rrrr_eeee_ssss_oooo_uuuu_rrrr_cccc_eeee_...._hhhh_>>>> _pppp_iiii_dddd______tttt _wwww_aaaa_iiii_tttt_3333 _((((_iiii_nnnn_tttt _****_ssss_tttt_aaaa_tttt_pppp_tttt_rrrr_,,,, _iiii_nnnn_tttt _oooo_pppp_tttt_iiii_oooo_nnnn_ssss_,,,, _ssss_tttt_rrrr_uuuu_cccc_tttt _rrrr_uuuu_ssss_aaaa_gggg_eeee _****_rrrr_uuuu_ssss_aaaa_gggg_eeee_))))_;;;; DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN _wwww_aaaa_iiii_tttt suspends the calling process until one of the immediate children terminate, or until a child that is being traced stops because it has hit an event of interest. The _wwww_aaaa_iiii_tttt will return prematurely if a signal is received. If all child processes stopped or terminated prior to the call on _wwww_aaaa_iiii_tttt, return is immediate. If the call is successful, the process ID of a child is returned. _wwww_aaaa_iiii_tttt_3333 is BSD's extension of _wwww_aaaa_iiii_tttt. It provides an alternate interface for programs that must not block when collecting the status of child processes. _wwww_aaaa_iiii_tttt_pppp_iiii_dddd is POSIX's extension of _wwww_aaaa_iiii_tttt. The _pppp_iiii_dddd argument specifies a set of child processes for which status is requested. _wwww_aaaa_iiii_tttt_pppp_iiii_dddd only returns the status of a child process from this set. PPPPAAAARRRRAAAAMMMMEEEETTTTEEEERRRRSSSS ssssttttaaaattttppppttttrrrr ((((aaaallllllll ffffuuuunnnnccccttttiiiioooonnnnssss)))):::: If _s_t_a_t_p_t_r is non-zero, 16 bits of information called _s_t_a_t_u_s are stored in the low-order 16 bits of the location pointed to by _s_t_a_t_p_t_r. _S_t_a_t_u_s may be evaluated with the macros described on _wwww_ssss_tttt_aaaa_tttt(5). _S_t_a_t_u_s can be used to differentiate between stopped and terminated child processes. If the child process terminated, _s_t_a_t_u_s identifies the cause of termination and passes useful information to the parent. _s_t_a_t_u_s is interpreted as follows: If the child process stopped, the predicate WWWWIIIIFFFFSSSSTTTTOOOOPPPPPPPPEEEEDDDD(*_s_t_a_t_p_t_r) will evaluate to non-zero and WWWWSSSSTTTTOOOOPPPPSSSSIIIIGGGG(*_s_t_a_t_p_t_r) will return the signal number that caused the process to stop. (The high-order 8 bits of _s_t_a_t_u_s will contain the signal number and the low-order 8 bits are set equal to _WWWW_SSSS_TTTT_OOOO_PPPP_FFFF_LLLL_GGGG.) If the child process terminated due to an _eeee_xxxx_iiii_tttt call, the predicate WWWWIIIIFFFFEEEEXXXXIIIITTTTEEEEDDDD(*_s_t_a_t_p_t_r) will evaluate to non-zero, and WWWWEEEEXXXXIIIITTTTSSSSTTTTAAAATTTTUUUUSSSS(*_s_t_a_t_p_t_r) will return the argument that the child process passed to ______eeee_xxxx_iiii_tttt or _eeee_xxxx_iiii_tttt, or the value the child process PPPPaaaaggggeeee 1111 WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) returned from _m_a_i_n [see _e_x_i_t(2)]. (The low-order 8 bits of _s_t_a_t_u_s will be zero and the high-order 8 bits will contain the low-order 8 bits of the argument that the child process passed to _eeee_xxxx_iiii_tttt.) If the child process terminated due to a signal, the predicate WWWWIIIIFFFFSSSSIIIIGGGGNNNNAAAALLLLEEEEDDDD(*_s_t_a_t_p_t_r) will evaluate to non-zero, and WWWWTTTTEEEERRRRMMMMSSSSIIIIGGGG(*_s_t_a_t_p_t_r) will return the signal number that caused the termination. (The high-order 8 bits of _s_t_a_t_u_s will be zero and the low-order 8 bits will contain the number of the signal.) In addition, if _WWWW_CCCC_OOOO_RRRR_EEEE_FFFF_LLLL_GGGG is set, a ``core image'' will have been produced [see _s_i_g_n_a_l(2)]. rrrruuuussssaaaaggggeeee ((((wwwwaaaaiiiitttt3333)))):::: If _r_u_s_a_g_e non-zero, a summary of the resources used by the terminated process and all its children is returned (this information is currently not available for stopped processes). ppppiiiidddd ((((wwwwaaaaiiiittttppppiiiidddd)))):::: 1) If _p_i_d is equal to -1, status is requested for any child process. In this respect, _wwww_aaaa_iiii_tttt_pppp_iiii_dddd is then equivalent to _wwww_aaaa_iiii_tttt. 2) If _p_i_d is greater than zero, it specifies the process ID of a single child process for which status is requested. 3) If _p_i_d is equal to zero, status is requested for any child process whose process group ID is equal to that of the calling process. 4) If _p_i_d is less than -1, status is requested for any child process whose process group ID is equal to the absolute value of _p_i_d. ooooppppttttiiiioooonnnnssss ((((wwwwaaaaiiiittttppppiiiidddd aaaannnndddd wwwwaaaaiiiitttt3333)))):::: The _o_p_t_i_o_n_s _a_r_g_u_m_e_n_t is constructed from the bitwise inclusive OR of zero or more of the following flags, defined in the header <_s_y_s/_w_a_i_t._h>: WNOHANG The function will not suspend execution of the calling process if status is not immediately available for one of the child processes. WUNTRACED The status of child processes that are stopped due to a SSSSIIIIGGGGTTTTTTTTIIIINNNN, SSSSIIIIGGGGTTTTTTTTOOOOUUUU, SSSSIIIIGGGGTTTTSSSSTTTTPPPP, or SSSSIIIIGGGGSSSSTTTTOOOOPPPP signal, and whose status has not yet been reported since they stopped, are reported to the requesting process. If a parent process terminates without waiting for its child processes to terminate, the parent process ID of each child process is set to 1. This means the initialization process inherits the child processes [see _i_n_t_r_o(2)]. PPPPaaaaggggeeee 2222 WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) SIGCLD HANDLING IRIX has three distinct version of signal routines: System V (_ssss_iiii_gggg_nnnn_aaaa_llll(2) and _ssss_iiii_gggg_ssss_eeee_tttt(2)), 4.3BSD (_ssss_iiii_gggg_nnnn_aaaa_llll(3B) and _ssss_iiii_gggg_vvvv_eeee_cccc(3B)), and POSIX (_ssss_iiii_gggg_aaaa_cccc_tttt_iiii_oooo_nnnn(2)). Each version has a method by which a parent can be certain that it waits on all of its children even if they are executing concurrently. In each version, the parent installs a signal handler for SSSSIIIIGGGGCCCCLLLLDDDD to wait for its children, but the specific code differs in subtle, albeit vital, ways. Sample programs below are used to illustrate each of the three methods. Note that System V refers to this signal as SSSSIIIIGGGGCCCCLLLLDDDD, whereas BSD calls it SSSSIIIIGGGGCCCCHHHHLLLLDDDD. For compatibility with both systems they are defined to be the same signal number, and may therefore be used interchangeably. SSSSyyyysssstttteeeemmmm VVVV:::: System V's SSSSIIIIGGGGCCCCLLLLDDDD mechanism guarantees that no SSSSIIIIGGGGCCCCLLLLDDDD signals will be lost. It accomplishes this by forcing the process to reinstall the handler (via _ssss_iiii_gggg_nnnn_aaaa_llll or _ssss_iiii_gggg_ssss_eeee_tttt calls) when leaving the handler. Note that whereas _ssss_iiii_gggg_nnnn_aaaa_llll(2) sets the signal disposition back to SSSSIIIIGGGG____DDDDFFFFLLLL each time the handler is called, _ssss_iiii_gggg_ssss_eeee_tttt(2) keeps it installed, so SSSSIIIIGGGGCCCCLLLLDDDD is the only signal that demands this reinstallation, and that only because the installation call allows the kernel to check for additional instances of the signal that occurred while the process was executing in the handler. The code below is the System V example. Note that the _ssss_iiii_gggg_pppp_aaaa_uuuu_ssss_eeee(2) creates a window during which SSSSIIIIGGGGCCCCLLLLDDDD is not blocked, allowing the parent to enter its handler. /* * System V example of wait-in-SIGCLD-handler usage */ #include <signal.h> #include <stdio.h> #include <sys/wait.h> static void handler(int); #define NUMKIDS 4 volatile int kids = NUMKIDS; main() { int i, pid; sigset(SIGCLD, handler); sighold(SIGCLD); for (i = 0; i < NUMKIDS; i++) { if (fork() == 0) { printf("Child %d\n", getpid()); exit(0); } } while (kids > 0) { sigpause(SIGCLD); PPPPaaaaggggeeee 3333 WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) sighold(SIGCLD); } } static void handler(int sig) { int pid, status; printf("Parent (%d) in handler, ", getpid()); pid = wait(&status); kids--; printf("child %d, now %d left\n", pid, kids); /* * Now reinstall handler & cause SIGCLD to be re-raised * if any more children exited while we were in here. */ sigset(SIGCLD, handler); } BBBBSSSSDDDD:::: 4.3BSD solved this problem differently: instead of guaranteeing that no SSSSIIIIGGGGCCCCHHHHLLLLDDDD signals are lost, it provides a WWWWNNNNOOOOHHHHAAAANNNNGGGG option to _wwww_aaaa_iiii_tttt_3333 that allows parent processes to do non-blocking waits in loops, until no more stopped or zombied children exist. Note that the handler must be able to deal with the case in which no applicable children exist; if one or more children exit while the parent is in the handler, all may get reaped, yet if one or more SSSSIIIIGGGGCCCCHHHHLLLLDDDD signals arrived while the parent was in its handler, the signal will remain pending, the parent will reenter the handler, and the _wwww_aaaa_iiii_tttt_3333 call will return 0. Note that it is not necessary to call _ssss_iiii_gggg_vvvv_eeee_cccc upon exit from the handler. /* * BSD example of wait3-in-SIGCHLD handler usage */ #define _BSD_SIGNALS #include <signal.h> #include <stdio.h> #include <sys/wait.h> static int handler(int); #define NUMKIDS 4 volatile int kids = NUMKIDS; main() { int i, pid; struct sigvec vec; vec.sv_handler = handler; PPPPaaaaggggeeee 4444 WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) vec.sv_mask = sigmask(SIGCHLD); vec.sv_flags = 0; sigvec(SIGCHLD, &vec, NULL); sigsetmask(sigmask(SIGCHLD)); for (i = 0; i < NUMKIDS; i++) { if (fork() == 0) { printf("Child %d\n", getpid()); exit(0); } } while (kids > 0) { sigpause(0); } } static int handler(int sig) { int pid; int status; printf("Parent (%d) in handler, ", getpid()); while ((pid = wait3(&status, WNOHANG, NULL)) > 0) { kids--; printf("child %d, now %d left\n", pid, kids); } } PPPPOOOOSSSSIIIIXXXX:::: POSIX improved on the BSD method by providing _wwww_aaaa_iiii_tttt_pppp_iiii_dddd, that allows a parent to wait on a particular child process if desired. In addition, the IRIX implementation of _ssss_iiii_gggg_aaaa_cccc_tttt_iiii_oooo_nnnn(2) checks for zombied children upon exit from the system call if the specified signal was SSSSIIIIGGGGCCCCLLLLDDDD and the disposition of the signal handling was changed. If zombied children exist, another SSSSIIIIGGGGCCCCLLLLDDDD is raised. This solves the problem that occurs when a parent creates children, but a module that it links with (typically a libc routine such as _ssss_yyyy_ssss_tttt_eeee_mmmm(3)) creates and waits on its own children. Two problems have classically arisen in such a scheme: 1) until the advent of _wwww_aaaa_iiii_tttt_pppp_iiii_dddd, the called routine could not specify which children to wait on; it therefore looped, waiting and discarding children until the one (or ones) it had created terminated, and 2) if the called routine changed the disposition of SSSSIIIIGGGGCCCCLLLLDDDD and then restored the previous handler upon exit, children of the parent (calling) process that had terminated while the called routine executed would be missed in the parent, because the called routine's SSSSIIIIGGGGCCCCLLLLDDDD handler would reap and discard those children. The addition of _wwww_aaaa_iiii_tttt_pppp_iiii_dddd and the IRIX implementation of _ssss_iiii_gggg_aaaa_cccc_tttt_iiii_oooo_nnnn solves both of these problems. Note that neither the BSD nor the System V signal routines on IRIX have these properties, in the interests of compatibility. PPPPaaaaggggeeee 5555 WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) WARNING: programs that install SSSSIIIIGGGGCCCCLLLLDDDD handlers that set flags instead of executing _wwww_aaaa_iiii_tttt_pppp_iiii_dddds and then attempt to restore the previous signal handler (via _ssss_iiii_gggg_aaaa_cccc_tttt_iiii_oooo_nnnn) upon return from the handler will create infinite loops. /* * POSIX example of waitpid-in-SIGCHLD handler usage */ #include <signal.h> #include <stdio.h> #include <sys/wait.h> static void handler(int); #define NUMKIDS 4 volatile int kids = NUMKIDS; /* * If waitpid's 1st argument is -1, it waits for any child. */ #define ANYKID -1 main() { int i; pid_t pid; struct sigaction act; sigset_t set, emptyset; act.sa_handler = handler; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGCHLD); act.sa_flags = 0; sigaction(SIGCHLD, &act, NULL); sigemptyset(&set); sigemptyset(&emptyset); sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, NULL); setbuf(stdout, NULL); for (i = 0; i < NUMKIDS; i++) { if (fork() == 0) { printf("Child %d\n", getpid()); exit(0); } } while (kids > 0) { sigsuspend(&emptyset); } } PPPPaaaaggggeeee 6666 WWWWAAAAIIIITTTT((((2222)))) WWWWAAAAIIIITTTT((((2222)))) static void handler(int sig) { pid_t pid; int status; printf("Parent (%d) in handler, ", getpid()); pid = waitpid(ANYKID, &status, WNOHANG); while (pid > 0) { kids--; printf("child %d, now %d left\n", pid, kids); pid = waitpid(ANYKID, &status, WNOHANG); } } DDDDIIIIAAAAGGGGNNNNOOOOSSSSTTTTIIIICCCCSSSS _wwww_aaaa_iiii_tttt fails and its actions are undefined if _s_t_a_t_p_t_r points to an invalid address. If _wwww_aaaa_iiii_tttt, _wwww_aaaa_iiii_tttt_3333, or _wwww_aaaa_iiii_tttt_pppp_iiii_dddd return due to a stopped or terminated child process, the process ID of the child is returned to the calling process. _wwww_aaaa_iiii_tttt_3333 and _wwww_aaaa_iiii_tttt_pppp_iiii_dddd return 0 if WWWWNNNNOOOOHHHHAAAANNNNGGGG is specified and there are currently no stopped or exited children (although children DO exist). Otherwise, a value of -1 is returned and _e_r_r_n_o is set to indicate the error: [EINTR] The calling process received a signal. [ECHILD] The calling process has no existing unwaited-for child processes. [ECHILD] The process or process group specified by _p_i_d does not exist or is not a child of the calling process (_wwww_aaaa_iiii_tttt_pppp_iiii_dddd only). [EFAULT] The _r_u_s_a_g_e or _s_t_a_t_p_t_r arguments (where applicable) point to illegal addresses. [EINVAL] The value of the _o_p_t_i_o_n_s argument is not valid (_wwww_aaaa_iiii_tttt_pppp_iiii_dddd and _wwww_aaaa_iiii_tttt_3333 only). SSSSEEEEEEEE AAAALLLLSSSSOOOO exec(2), exit(2), fork(2), intro(2), pause(2), ptrace(2), signal(2), sigset(2), sigpause(2), sigaction(2), sigsuspend(2), sigprocmask(2), signal(3B), sigvec(3B), sigpause(3B), wait(3b), getrusage(3), wstat(5). NNNNOOOOTTTTEEEE Currently, _wwww_aaaa_iiii_tttt_3333 returns zero for the _r_u__i_x_r_s_s, _r_u__i_d_r_s_s and _r_u__i_s_r_s_s fields in _r_u_s_a_g_e. PPPPaaaaggggeeee 7777